package com.rent.common.utils;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static cn.hutool.core.date.DatePattern.*;

public final class DateUtil {

    public static final String DEFAULT_YEAR_FORMAT = "yyyy";
    public static final String DEFAULT_MONTH_FORMAT = "yyyy-MM";
    public static final String DEFAULT_MONTH_FORMAT_SLASH = "yyyy/MM";
    public static final String DEFAULT_MONTH_FORMAT_EN = "yyyy年MM月";
    public static final String DEFAULT_WEEK_FORMAT = "yyyy-ww";
    public static final String DEFAULT_WEEK_FORMAT_EN = "yyyy年ww周";
    public static final String DEFAULT_DATE_FORMAT = NORM_DATE_PATTERN;
    public static final String DEFAULT_DATE_FORMAT_EN = CHINESE_DATE_PATTERN;
    public static final String DEFAULT_DATE_TIME_FORMAT = NORM_DATETIME_PATTERN;
    public static final String DEFAULT_DATE_TIME_FORMAT_EN = CHINESE_DATE_TIME_PATTERN;
    public static final String DEFAULT_TIME_FORMAT = NORM_TIME_PATTERN;
    public static final String DAY = "DAY";
    public static final String MONTH = "MONTH";
    public static final String WEEK = "WEEK";

    public static final String DEFAULT_DATE_FORMAT_MATCHES = "^\\d{4}-\\d{1,2}-\\d{1,2}$";
    public static final String DEFAULT_DATE_TIME_FORMAT_MATCHES = "^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$";
    public static final String DEFAULT_DATE_FORMAT_EN_MATCHES = "^\\d{4}年\\d{1,2}月\\d{1,2}日$";
    public static final String DEFAULT_DATE_TIME_FORMAT_EN_MATCHES = "^\\d{4}年\\d{1,2}月\\d{1,2}日\\d{1,2}时\\d{1,2}分\\d{1,2}秒$";
    public static final String SLASH_DATE_FORMAT_MATCHES = "^\\d{4}/\\d{1,2}/\\d{1,2}$";
    public static final String SLASH_DATE_TIME_FORMAT_MATCHES = "^\\d{4}/\\d{1,2}/\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$";
    public static final String SLASH_DATE_FORMAT = "yyyy/MM/dd";
    public static final String SLASH_DATE_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss";
    public static final String CRON_FORMAT = "ss mm HH dd MM ? yyyy";


    /**
     * 转换 LocalDateTime 为 cron , eg.  "0 07 10 15 1 ? 2016"
     *
     * @param date 时间点
     * @return cron 表达式
     */
    public static String getCron(LocalDateTime date) {
        return format(date, CRON_FORMAT);
    }

    /**
     * 格式化日期,返回格式为 yyyy-MM
     *
     * @param date 日期
     * @return 格式化后的字符串
     */
    public static String format(LocalDateTime date, String pattern) {
        if (date == null) {
            date = LocalDateTime.now();
        }
        if (pattern == null) {
            pattern = DEFAULT_MONTH_FORMAT;
        }
        return date.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String format(LocalDate date, String pattern) {
        if (date == null) {
            date = LocalDate.now();
        }
        if (pattern == null) {
            pattern = DEFAULT_MONTH_FORMAT;
        }
        return date.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * LocalDateTime转换为Date
     *
     * @param localDateTime 日期
     * @return 解析后的日期
     */
    public static Date localDateTimeDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    //--解析日期 end-----------------------------------------


    /**
     * Date转换为LocalDateTime
     *
     * @param date 日期
     */
    public static LocalDateTime dateLocalDateTime(Date date) {
        if (date == null) {
            return LocalDateTime.now();
        }
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /**
     * 获取当前时间
     * "yyyy-MM-dd HH:mm:ss
     *
     * @return string
     */
    public static String getCurrentTime() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return formatter.format(currentTime);
    }

    /**
     * 返回yyyy-MM-dd HH:mm:ss 格式字符串
     */
    public static String dateForString(Date date, String format) {
        if (date == null) return null;
        if (format == null || format.length() == 0) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        try {
            SimpleDateFormat formatter = new SimpleDateFormat(format);
            return formatter.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 获取星期几
    public static int getWeekOfDate(Date date) {
        if (date == null) date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK) - 1;
    }

    /**
     * 获取当前时间
     * "yyyyMMddHHmmss
     *
     * @return 字符串
     */
    public static String nowDateString() {
        try {
            Calendar now = Calendar.getInstance();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            Date date = now.getTime();
            return sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取当前时间年月日
     * "yyyyMMdd
     */
    public static String nowTime() {
        Calendar now = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = now.getTime();
        return sdf.format(date);
    }

    /**
     * 获取当期时间 仅到分钟
     * yyyy年MM月dd日 HH:mm
     */
    public static String currentDateStringLocal() {
        Calendar now = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
        Date date = now.getTime();
        return sdf.format(date);
    }

    /**
     * 通过字符串获取时间 格式yyyyMMddHHmmss
     */
    public static Date dateByString(String msg) {
        if (msg == null || "".equals(msg)) {
            return null;
        }
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            return formatter.parse(msg);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 格式化获取时间
     */
    public static Date dateByStringFormat(String msg, String format) {
        if (msg == null || "".equals(msg)) {
            return null;
        }
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        try {
            return formatter.parse(msg);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将时间戳转换为时间字符串yyyy-MM-dd HH:mm:ss
     */
    public static String stampToDateStr(String s) {
        if (s == null || s.length() == 0) {
            return null;
        }
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt = new Long(s);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }

    /**
     * 将时间戳转换为时间
     */
    public static Date stampToDate(String s) {
        if (s == null || s.length() == 0) {
            return new Date();
        }
        long lt = new Long(s);
        return new Date(lt);
    }

    /**
     * 将时间转换为时间戳
     */
    public static String dateToStamp(String s) throws ParseException {
        if (s == null || s.length() == 0) {
            return null;
        }
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        res = String.valueOf(ts);
        return res;
    }

    /**
     * 日期转换成字符串 yyyy-MM-dd HH:mm:ss
     */
    public static String dateString(Date date) {
        if (date == null) return null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

    /**
     * 转化时间
     */
    public static Date stringToDate(String time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 转化时间
     */
    public static Date excelStringToDate(String time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = null;
        try {
            date = sdf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 获得明年当日
     */
    public static Date getDateByYearDay() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR) + 1, cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        Date beginOfDate = cal.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String string = formatter.format(beginOfDate);
        try {
            return formatter.parse(string);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return new Date();
    }


    /**
     * 获得当天零时零分零秒
     */
    public static Date initDateByDay() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        Date beginOfDate = cal.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String string = formatter.format(beginOfDate);
        try {
            return formatter.parse(string);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获得当月第一天零时零分零秒
     */
    public static Date initDateByMonth() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 1, 0, 0, 0);
        Date beginOfDate = cal.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String string = formatter.format(beginOfDate);
        try {
            return formatter.parse(string);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获得本周第一天零时零分零秒
     */
    public static Date initDateByWeek() {
        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
        //将小时至0
        cal.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        cal.set(Calendar.MINUTE, 0);
        //将秒至0
        cal.set(Calendar.SECOND, 0);
        //将毫秒至0
        cal.set(Calendar.MILLISECOND, 0);
        Date beginOfDate = cal.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String string = formatter.format(beginOfDate);
        try {
            return formatter.parse(string);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获得本年第一天零时零分零秒
     */
    public static Date initDateByYear() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), 0, 1, 0, 0, 0);
        Date beginOfDate = cal.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String string = formatter.format(beginOfDate);
        try {
            return formatter.parse(string);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 时间戳转日期
     */
    public static Date transForDate(Integer ms) {
        if (ms == null) {
            ms = 0;
        }
        long msl = (long) ms * 1000;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date temp = null;
        try {
            String str = sdf.format(msl);
            temp = sdf.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return temp;
    }

    /**
     * 时间戳转换成日期格式字符串
     */
    public static String timeStamp2Date(String seconds, String format) {
        if (seconds == null || seconds.isEmpty() || seconds.equals("null")) {
            return "";
        }
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date(Long.parseLong(seconds + "000")));
    }

    /**
     * 日期格式字符串转换成时间戳
     */
    public static String date2TimeStamp(String date_str, String format) {
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return String.valueOf(sdf.parse(date_str).getTime() / 1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 日期格式字符串转换成时间
     */
    public static Date StringToDateFormat(String date_str, String format) {
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.parse(date_str);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 取得当前时间戳（精确到秒）
     */
    public static String currentTimeStamp() {
        long time = System.currentTimeMillis();
        return String.valueOf(time / 1000);
    }

    /**
     * 判断 当前时间  是否超时 超时true
     */
    public static boolean isOvertime(Date create_time, Integer expiresIn) {
        long current_time = System.currentTimeMillis() / 1000;
        long inTime = create_time.getTime() + (long) expiresIn;
        return current_time >= inTime;
    }

    /**
     * 时间对分钟运算相加
     */
    public static Date minuteDateCalculate(Date date, int minute) {
        if (date == null) date = new Date();
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.MINUTE, minute);//时间加分钟
        return rightNow.getTime();
    }

    /**
     * 时间对天运算相加
     */
    public static Date dayCalculate(Date date, int day) {
        if (date == null) date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, day);//时间加天
        return calendar.getTime();
    }

    /**
     * 时间对月运算
     */
    public static Date monthCalculate(Date date, int month) {
        if (date == null) date = new Date();
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.MONTH, 1);//时间加1月
        return rightNow.getTime();
    }

    /**
     * 时间对年运算
     */
    public static Date yearCalculate(Date date, int year) {
        if (date == null) date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, 1);//时间加1年
        return calendar.getTime();
    }


    /**
     * 当前时间对分钟运算,返回Date
     */
    public static Date hourDateCalculate(Date date, int hour) {
        if (date == null) date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, hour);// 时间减分钟
        return calendar.getTime();
    }


    /**
     * 判断字符串日期大小，Date1>Date2  返回1
     */
    public static int compare_date(String DATE1, String DATE2) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {

            Date dt1 = df.parse(DATE1);
            Date dt2 = df.parse(DATE2);
            return Long.compare(dt1.getTime(), dt2.getTime());
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return 0;
    }

    /**
     * 比较时间A是否大于B 大于true
     *
     * @return 是否
     */
    public static Boolean compareDate(Date dateA, Date dateB) {
        if (dateA == null || dateB == null) return false;
        return dateA.getTime() > dateB.getTime();
    }

    /**
     * 比较时间是否大于当前时间
     */
    public static Boolean compareToDate(Date from) {
        if (from == null) return true;
        Date date = new Date();
        return from.getTime() > date.getTime();
    }

    public static String checkDateStr(String date) {
        if (StringUtils.isEmpty(StringUtils.trim(date))) {
            return getCurrentDate();
        }
        return date;
    }

    public static String getCurrentDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        return sdf.format(date);
    }

    /**
     * 返回当前的系统的年份
     */
    public static String getCurrentYear() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY");
        return sdf.format(date);
    }

    /**
     * 返回当前系统的月份
     */
    public static String getCurrentMonth() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("MM");
        return sdf.format(date);
    }

    /**
     * 获取当前月份的每一天
     *
     * @return 列表
     */
    public static List<String> getCurrentDayByMonth() {
        Calendar cal = Calendar.getInstance();
        int month = cal.get(Calendar.MONTH);
        int year = cal.get(Calendar.YEAR);
        int day = cal.get(Calendar.DAY_OF_MONTH);
        return getDayByMonth(year, month, day);
    }

    /**
     * 获取月份的每一天
     *
     * @param yearParam  年
     * @param monthParam 月
     * @return 列表
     */
    public static List<String> getDayByMonth(int yearParam, int monthParam, int dayParam) {
        List<String> list = new ArrayList<>();
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        aCalendar.set(yearParam, monthParam, dayParam);
        int year = aCalendar.get(Calendar.YEAR);//年份
        int month = aCalendar.get(Calendar.MONTH) + 1;//月份
        int day = aCalendar.get(Calendar.DAY_OF_MONTH);
        for (int i = 1; i <= day; i++) {
            String aDate = null;
            if (month < 10 && i < 10) {
                aDate = "0" + month + "-0" + i;
            }
            if (month < 10 && i >= 10) {
                aDate = "0" + month + "-" + i;
            }
            if (month >= 10 && i < 10) {
                aDate = month + "-0" + i;
            }
            if (month >= 10 && i >= 10) {
                aDate = month + "-" + i;
            }
            aDate = year + "-" + aDate;
            list.add(aDate);
        }
        return list;
    }


    /**
     * 计算时间
     *
     * @param startTime ： 开始时间
     * @param endTime   ： 结束时间
     */
    public static int caculateTotalDays(String startTime, String endTime) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Date date1;
        Date date;
        long l = 0L;
        try {
            date = formatter.parse(startTime);
            long ts = date.getTime();
            date1 = formatter.parse(endTime);
            long ts1 = date1.getTime();

            l = (ts1 - ts) / (1000 * 60 * 60 * 24);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        return (int) l;
    }


    /**
     * 计算时间相差天数
     *
     * @param startTime ： 开始时间
     * @param endTime   ： 结束时间
     * @return 天数
     */
    public static int caculateTotalDays(Date startTime, Date endTime) {
        if (startTime == null || endTime == null) {
            return 0;
        }
        long l = 0L;
        try {
            long ts = startTime.getTime();
            long ts1 = endTime.getTime();
            l = (ts1 - ts) / (1000 * 60 * 60 * 24);
            l = Math.abs(l);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (int) l;
    }


}
